package com.cqc.jdk8.Jutil.concurrent;

import org.junit.Test;

import java.util.concurrent.*;

/**
 * @author cui
 * @date 2023/11/12 18:11
 * @description
 **/
public class CompletableFutureTest {


    /**
     * thenAccept(Consumer) 有入参，没有返回值
     */
    @Test
    public void f9() throws Exception {
        CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> 1)
                .thenAccept(x -> {
                    System.out.println(1);
                    int a = 1 / 0;
                })
                .thenAccept(x -> {
                    //上一步不报错，才会走到 thenAccept
                    System.out.println(2);
                })
                .exceptionally(e -> {
                    System.out.println(e);
                    return null;
                });
        System.out.println(future.get());
    }


    /**
     * thenRun(Runnable) 没有入参，没有返回值
     */
    @Test
    public void f8() throws Exception {
        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 1)
                .thenRun(() -> {
                    System.out.println(1);
                })
                .thenRun(() -> {
                    System.out.println(2);
                })
                .thenApply(x -> 3)
                .exceptionally(e -> {
                    return null;
                });
        System.out.println(future.get());
    }


    /**
     * handle(preResult,throwable)对上一步的结果、异常进行处理
     * 发生异常，那么异常后的handle()还是会执行，最后返回exceptionally指定的值
     */
    @Test
    public void f6() throws Exception {
        Integer integer = CompletableFuture.supplyAsync(() -> 1)
                .handle((x, e) -> {
                    System.out.println("这是第1个handle");
                    if (null != e) {
                        System.out.println("上一步supplyAsync发生了异常");
                    }
                    x = x / 0;
                    return x + 1;
                })
                .handle((x, e) -> {
                    System.out.println("这是第2个handle");
                    if (null != e) {
                        System.out.println("上一步handle发生了异常");
                    }
                    return x + 2;
                })
                .exceptionally(e -> 100)
                .get();
        System.out.println(integer);
    }

    /**
     * thenApply() 对上一步的结果进行处理。
     * 发生异常，那么异常后的thenApply()不再执行，直接到 exceptionally()
     */
    @Test
    public void f5() throws Exception {
        Integer integer = CompletableFuture.supplyAsync(() -> {
                    return 1;
                }).thenApply(x -> {
                    x = x / 0;
                    return x + 1;
                }).whenComplete((x, e) -> {
                    System.out.println("whenComplete1:" + x);
                }).thenApply(x -> {
                    return x + 2;
                }).whenComplete((x, e) -> {
                    System.out.println("whenComplete2:" + x);
                })
                .exceptionally(e -> {
                    System.out.println("异常：" + e.getMessage());
                    return -1;
                }).get();
        System.out.println(integer);
    }


    /**
     *
     */
    @Test
    public void f4() throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("执行任务runnable," + Thread.currentThread().getName());
        }, executor).whenComplete((r, t) -> {
            System.out.println("执行结果是 r=" + r);
        }).exceptionally(e -> {
            e.printStackTrace();
            return null;
        });

    }

    /**
     * 对f2()方法的优化
     */
    @Test
    public void f3() throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        CompletableFuture<String> future = CompletableFuture
                .supplyAsync(this::sleep1Second, executor)
                .whenComplete(this::complete)
                .exceptionally(this::handleException);
        String result = future.get();
        System.out.println("结果" + result);
    }

    private String sleep1Second() {
        System.out.println("第一步， supplyAsync");
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "supplyAsync";
    }

    private <T> String complete(T result, Throwable throwable) {
        System.out.println("第2布，whenComplete，上一步的执行结果是 result=" + result);
        return "whenComplete";
    }

    private String handleException(Throwable throwable) {
        throwable.printStackTrace();
        return "异常：" + throwable.getMessage();
    }


    /**
     * 使用自定义的线程池，必须等到子线程走完，主线程才会清除子线程。
     */
    @Test
    public void f2() throws Exception {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("执行任务runnable");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, executor).whenComplete((r, t) -> {
            System.out.println("执行结果是 r=" + r);
        }).exceptionally(e -> {
            e.printStackTrace();
            return null;
        });
        Void aVoid = future.get();
    }

    /**
     * 使用默认的线程池 ForkJoinPool，如果主线程走完了，就会把子线程都停掉。
     * 所以一般会让主线程等待几秒，等到子线程执行完毕。
     * 如果不阻塞主线程，发现只执行了 runAsync，没有执行 whenComplete
     */
    @Test
    public void f1() throws Exception {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("执行任务runnable");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).whenComplete((r, t) -> {
            //主线程不加sleep(),就不会走到这个方法
            System.out.println("执行结果是 r=" + r);
        }).exceptionally(e -> {
            e.printStackTrace();
            return null;
        });
//        future.join();
        TimeUnit.SECONDS.sleep(3);//阻塞主线程
    }

}
